package com.example.kotlinlearndemo.kotlin

import com.google.gson.*
import java.lang.reflect.Type

fun main() {
    GsonTest().test()
}

/**
 * Created by zmx on 2021/12/17 15:00
 *
 */
class GsonTest {

    val gson: Gson
        get() {
            return GsonBuilder()
                .registerTypeAdapter(User::class.java, UserDeserializer())
                .registerTypeAdapter(User.Foo::class.java, UserFooDeserializer())
                .registerTypeAdapter(Admin::class.java, AdminDeserializer())
                .registerTypeAdapter(Guest::class.java, GuestDeserializer())
                .serializeNulls()
                .create()
        }

    fun toUser(json: String?) {
        val user = gson.fromJson(json, User::class.java)
        println(user?.foo?.boo)
    }

    fun test() {
        val t1 = "{\"id\":\"123\"}"
        val t2 = "{\"abc\":\"123\"}"

//        toUser(t1)
//        toUser(t2)
//        toUser("")
//        toUser("null")
//        toUser(null)

        toUser("{\"id\":\"123\",\"foo\":\"string\"}")
//        toUser("{\"id\":\"123\",\"foo\":{\"boo\":\"value\"}}")
    }

}

class UserDeserializer : JsonDeserializer<User> {

    @Throws(JsonParseException::class)
    override fun deserialize(
        json: JsonElement?, typeOF: Type?,
        context: JsonDeserializationContext?,
    ): User? {
        println("12345: user")
        json?.let {
            val user = User()
            try {
                json.asJsonObject?.let {
                    user.id = it["id"].asString
                    user.foo = context?.deserialize(it, User.Foo::class.java)
                }
                return user
            } catch (e: Exception) {
                error(e.message ?: "")
            }
        }

        return null
    }
}

class UserFooDeserializer : JsonDeserializer<User.Foo> {
    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?,
    ): User.Foo? {
        println("12345: user.foo")
        json?.let {
            try {
                return json.asJsonObject?.let {
                    return User.Foo().apply {
                        boo = it["boo"].asString
                    }
                }
            } catch (e: Exception) {
            }
        }
        return null
    }

}

class AdminDeserializer : JsonDeserializer<Admin> {

    @Throws(JsonParseException::class)
    override fun deserialize(
        json: JsonElement?, typeOF: Type,
        context: JsonDeserializationContext,
    ): Admin? {
        println("12345: admin")
        return null
    }
}

class GuestDeserializer : JsonDeserializer<Guest> {

    @Throws(JsonParseException::class)
    override fun deserialize(
        json: JsonElement?, typeOF: Type,
        context: JsonDeserializationContext,
    ): Guest? {
        println("12345: guest")
        return null
    }
}


class User {
    var id: String? = null
    var foo: Foo? = null

    class Foo {
        var boo: String? = null
    }
}

class Admin {
    var id: String? = null
}

class Guest {
    var name: String? = null
}